package com.tungsten.fcl.ui.download;

import static com.tungsten.fcllibrary.util.LocaleUtils.formatDateTime;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.appcompat.app.AlertDialog;

import com.mio.util.AnimUtil;
import com.tungsten.fcl.R;
import com.tungsten.fcl.util.AndroidUtils;
import com.tungsten.fclcore.download.RemoteVersion;
import com.tungsten.fclcore.download.fabric.FabricAPIRemoteVersion;
import com.tungsten.fclcore.download.fabric.FabricRemoteVersion;
import com.tungsten.fclcore.download.forge.ForgeRemoteVersion;
import com.tungsten.fclcore.download.game.GameRemoteVersion;
import com.tungsten.fclcore.download.liteloader.LiteLoaderRemoteVersion;
import com.tungsten.fclcore.download.neoforge.NeoForgeRemoteVersion;
import com.tungsten.fclcore.download.optifine.OptiFineRemoteVersion;
import com.tungsten.fclcore.download.quilt.QuiltAPIRemoteVersion;
import com.tungsten.fclcore.download.quilt.QuiltRemoteVersion;
import com.tungsten.fcllibrary.component.FCLAdapter;
import com.tungsten.fcllibrary.component.theme.ThemeEngine;
import com.tungsten.fcllibrary.component.view.FCLImageButton;
import com.tungsten.fcllibrary.component.view.FCLImageView;
import com.tungsten.fcllibrary.component.view.FCLLinearLayout;
import com.tungsten.fcllibrary.component.view.FCLTextView;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class RemoteVersionListAdapter extends FCLAdapter {

    private final ArrayList<RemoteVersion> list;
    private final OnRemoteVersionSelectListener listener;

    public RemoteVersionListAdapter(Context context, ArrayList<RemoteVersion> list, OnRemoteVersionSelectListener listener) {
        super(context);
        this.list = list;
        this.listener = listener;
    }

    private static class ViewHolder {
        FCLLinearLayout parent;
        FCLImageView icon;
        FCLTextView version;
        FCLTextView tag;
        FCLTextView date;
        FCLImageButton wiki;
        FCLImageButton save;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int i) {
        return list.get(i);
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        final ViewHolder viewHolder;
        if (view == null) {
            viewHolder = new ViewHolder();
            view = LayoutInflater.from(getContext()).inflate(R.layout.item_remote_version, null);
            viewHolder.parent = view.findViewById(R.id.parent);
            viewHolder.icon = view.findViewById(R.id.icon);
            viewHolder.version = view.findViewById(R.id.version);
            viewHolder.tag = view.findViewById(R.id.tag);
            viewHolder.date = view.findViewById(R.id.date);
            viewHolder.wiki = view.findViewById(R.id.wiki);
            viewHolder.save = view.findViewById(R.id.save);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }
        RemoteVersion remoteVersion = list.get(i);
        viewHolder.parent.setOnClickListener(view1 -> listener.onSelect(remoteVersion));
        viewHolder.icon.setBackground(getIcon(remoteVersion));
        viewHolder.version.setText(remoteVersion.getSelfVersion());
        viewHolder.tag.setBackground(getContext().getDrawable(R.drawable.bg_container_white));
        viewHolder.tag.setAutoBackgroundTint(true);
        viewHolder.tag.setBackgroundTintList(new ColorStateList(new int[][]{{}}, new int[]{ThemeEngine.getInstance().getTheme().getColor()}));
        viewHolder.tag.setText(getTag(remoteVersion));
        viewHolder.date.setVisibility(remoteVersion.getReleaseDate() == null ? View.GONE : View.VISIBLE);
        viewHolder.date.setText(remoteVersion.getReleaseDate() == null ? "" : formatDateTime(getContext(), remoteVersion.getReleaseDate()));
        if (remoteVersion instanceof GameRemoteVersion && (remoteVersion.getVersionType() == RemoteVersion.Type.RELEASE || remoteVersion.getVersionType() == RemoteVersion.Type.SNAPSHOT)) {
            viewHolder.wiki.setVisibility(View.VISIBLE);
            String wikiUrlSuffix = getWikiUrlSuffix(getContext(), remoteVersion.getGameVersion());
            viewHolder.wiki.setOnClickListener(v -> AndroidUtils.openLink(getContext(), getContext().getString(R.string.wiki_game, wikiUrlSuffix)));
        } else {
            viewHolder.wiki.setVisibility(View.GONE);
        }
        if (!(remoteVersion instanceof GameRemoteVersion) && !(remoteVersion instanceof FabricAPIRemoteVersion) && !(remoteVersion instanceof QuiltAPIRemoteVersion)) {
            viewHolder.save.setVisibility(View.VISIBLE);
            viewHolder.save.setOnClickListener(v -> {
                List<String> urls = remoteVersion.getUrls();
                new AlertDialog.Builder(getContext())
                        .setTitle(R.string.message_select_url)
                        .setItems(urls.toArray(new String[0]), (d, w) -> AndroidUtils.openLink(getContext(), urls.get(w)))
                        .setNegativeButton(R.string.button_cancel, null)
                        .create().show();
            });
        } else {
            viewHolder.save.setVisibility(View.GONE);
        }
        AnimUtil.playTranslationX(view, ThemeEngine.getInstance().getTheme().getAnimationSpeed() * 30L, -100f, 0f).start();
        return view;
    }

    @SuppressLint("UseCompatLoadingForDrawables")
    private Drawable getIcon(RemoteVersion remoteVersion) {
        if (remoteVersion instanceof LiteLoaderRemoteVersion)
            return getContext().getDrawable(R.drawable.img_chicken);
        else if (remoteVersion instanceof OptiFineRemoteVersion)
            return getContext().getDrawable(R.drawable.img_optifine);
        else if (remoteVersion instanceof ForgeRemoteVersion)
            return getContext().getDrawable(R.drawable.img_forge);
        else if (remoteVersion instanceof NeoForgeRemoteVersion)
            return getContext().getDrawable(R.drawable.img_neoforge);
        else if (remoteVersion instanceof FabricRemoteVersion || remoteVersion instanceof FabricAPIRemoteVersion)
            return getContext().getDrawable(R.drawable.img_fabric);
        else if (remoteVersion instanceof QuiltRemoteVersion || remoteVersion instanceof QuiltAPIRemoteVersion)
            return getContext().getDrawable(R.drawable.img_quilt);
        else if (remoteVersion instanceof GameRemoteVersion) {
            switch (remoteVersion.getVersionType()) {
                case RELEASE:
                    return getContext().getDrawable(R.drawable.img_grass);
                case SNAPSHOT:
                    return getContext().getDrawable(R.drawable.img_command);
                default:
                    return getContext().getDrawable(R.drawable.img_craft_table);
            }
        } else {
            return getContext().getDrawable(R.drawable.img_grass);
        }
    }

    private String getTag(RemoteVersion remoteVersion) {
        if (remoteVersion instanceof GameRemoteVersion) {
            switch (remoteVersion.getVersionType()) {
                case RELEASE:
                    return getContext().getString(R.string.version_game_release);
                case SNAPSHOT:
                    return getContext().getString(R.string.version_game_snapshot);
                default:
                    return getContext().getString(R.string.version_game_old);
            }
        } else {
            return remoteVersion.getGameVersion();
        }
    }

    private String getWikiUrlSuffix(Context context, String gameVersion) {
        String id = gameVersion.toLowerCase(Locale.ROOT);

        switch (id) {
            case "0.30-1":
            case "0.30-2":
            case "c0.30_01c":
                return context.getString(R.string.wiki_game_search, "Classic_0.30");
            case "in-20100206-2103":
                return context.getString(R.string.wiki_game_search, "Indev_20100206");
            case "inf-20100630-1":
                return context.getString(R.string.wiki_game_search, "Infdev_20100630");
            case "inf-20100630-2":
                return context.getString(R.string.wiki_game_search, "Alpha_v1.0.0");
            case "1.19_deep_dark_experimental_snapshot-1":
                return "1.19-exp1";
            case "in-20100130":
                return context.getString(R.string.wiki_game_search, "Indev_0.31_20100130");
            case "b1.6-tb3":
                return context.getString(R.string.wiki_game_search, "Beta_1.6_Test_Build_3");
        }

        if (id.startsWith("1.0.0-rc2")) return "RC2";
        if (id.startsWith("2.0")) return context.getString(R.string.wiki_game_search, "2.0");
        if (id.startsWith("b1.8-pre1")) return "Beta_1.8-pre1";
        if (id.startsWith("b1.1-")) return context.getString(R.string.wiki_game_search, "Beta_1.1");
        if (id.startsWith("a1.1.0")) return "Alpha_v1.1.0";
        if (id.startsWith("a1.0.14")) return "Alpha_v1.0.14";
        if (id.startsWith("a1.0.13_01")) return "Alpha_v1.0.13_01";
        if (id.startsWith("in-20100214"))
            return context.getString(R.string.wiki_game_search, "Indev_20100214");

        if (id.contains("experimental-snapshot")) {
            return id.replace("-experimental-snapshot", "-exp");
        }

        if (id.startsWith("inf-")) return id.replace("inf-", "Infdev_");
        if (id.startsWith("in-")) return id.replace("in-", "Indev_");
        if (id.startsWith("rd-")) return "pre-Classic_" + id;
        if (id.startsWith("b")) return id.replace("b", "Beta_");
        if (id.startsWith("a")) return id.replace("a", "Alpha_v");
        if (id.startsWith("c")) return id.replace("c", "Classic_").replace("st", "SURVIVAL_TEST");

        return id;
    }

    public List<RemoteVersion> getList() {
        return list;
    }

    public interface OnRemoteVersionSelectListener {
        void onSelect(RemoteVersion remoteVersion);
    }
}
